#include "networking.h"

using namespace std;
/*
 * The third approach, uses select
 */

int      debug=0;
uint16_t serverport=21;
char     *hostname=NULL;

socketstream *ss;
int           sockfd;

static void
parse_args(int argc, char** argv) 
{
  int n = 1;
  while (n < argc) {
    if (strcmp(argv[n], "-h") == 0) {
      hostname = argv[++n];
    } else if (strcmp(argv[n], "-d") == 0) {
      debug = 1;
    } else if (strcmp(argv[n], "-p") == 0) {
      serverport = atoi(argv[++n]);
    } else
      err_quit("usage: %s [-h <hostname>] [-p <port>] [-d]", argv[0]);
    n++;
  }
  if (hostname == NULL)
    err_quit("usage: %s [-h <hostname>] [-p <port>] [-d]", argv[0]); 
}

int
main(int argc, char **argv)
{
  struct sockaddr_in	        servaddr;
  struct in_addr		**pptr;
  struct hostent		*hp;

  parse_args(argc, argv);


  // create a socket
  if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    err_quit("Cannot creat socket!");
  }
  
  // get server address
  if ( (hp = gethostbyname(hostname)) == NULL) {
    err_quit("Cannot resovle hostname!");
  }

  // parse the addresses
  pptr = (struct in_addr **) hp->h_addr_list;
  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(serverport);
  memcpy(&servaddr.sin_addr, *pptr, sizeof(struct in_addr));
  char charname[MAXLINE];
  if (debug) cerr << "Connect to server " << inet_ntop(AF_INET, &servaddr.sin_addr, charname, sizeof(charname)) << endl;
    
  // connect to the server
  if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0) {
    close(sockfd);
    err_quit("Cannot connect to server!");
  }

  // now start the loop

  ss = new socketstream(sockfd);

  int			maxfdp1, stdineof;
  fd_set		rset;
  char		        sendline[MAXLINE], recvline[MAXLINE];

  stdineof = 0;
  FD_ZERO(&rset);
  for ( ; ; ) {
    if (stdineof == 0)
      FD_SET(fileno(stdin), &rset);

    FD_SET(sockfd, &rset);

    maxfdp1 = max(fileno(stdin), sockfd) + 1;
    select(maxfdp1, &rset, NULL, NULL, NULL);
    
    if (FD_ISSET(sockfd, &rset)) {	/* socket is readable */
      if (ss->read_line(recvline, MAXLINE) == 0) {
	if (stdineof == 1)
	  return 0;		/* normal termination */
	else
	  err_quit("%s: server terminated", argv[0]);
      }
      
      fprintf(stdout, "%s\n", recvline);
    }
    
    if (FD_ISSET(fileno(stdin), &rset)) {  /* input is readable */
      if (fgets(sendline, MAXLINE, stdin) == NULL) {
	stdineof = 1;
	shutdown(sockfd, SHUT_WR);	/* send FIN */
	FD_CLR(fileno(stdin), &rset);
	continue;
      }
      
      ss->writen_socket(sendline, strlen(sendline));
    }
  }
}
